package org.hilo.boot.core.mapper;

import java.util.Set;

import org.apache.ibatis.mapping.MappedStatement;

import tk.mybatis.mapper.LogicDeleteException;
import tk.mybatis.mapper.annotation.LogicDelete;
import tk.mybatis.mapper.annotation.Version;
import tk.mybatis.mapper.entity.EntityColumn;
import tk.mybatis.mapper.mapperhelper.EntityHelper;
import tk.mybatis.mapper.mapperhelper.MapperHelper;
import tk.mybatis.mapper.mapperhelper.MapperTemplate;
import tk.mybatis.mapper.mapperhelper.SqlHelper;
import tk.mybatis.mapper.util.StringUtil;
import tk.mybatis.mapper.version.VersionException;

/**
 * @deprecated 使用不方面，建议使用select + update组合方式进行部分字段的更新
 * 
 * @author zollty
 * @since 2022年11月21日
 */
public class UpdateCustomFieldsProvider extends MapperTemplate {
    
    public UpdateCustomFieldsProvider(Class<?> mapperClass, MapperHelper mapperHelper) {
        super(mapperClass, mapperHelper);
    }

    /**
     * 更新指定的所有字段的值（包括空值也会更新）
     */
    public String updateCustomFields(MappedStatement ms) {
        Class<?> entityClass = getEntityClass(ms);
        StringBuilder sql = new StringBuilder();
        sql.append(SqlHelper.updateTable(entityClass, tableName(entityClass)));
        sql.append(updateSetColumns(entityClass, "record", "param", true, isNotEmpty()));
        sql.append(SqlHelper.wherePKColumns(entityClass, "record", true));
        return sql.toString();
    }
    
    /**
     * update set列
     *
     * @param entityClass
     * @param entityName  实体映射名
     * @param notNull     是否判断!=null
     * @param notEmpty    是否判断String类型!=''
     * @return
     */
    public static String updateSetColumns(Class<?> entityClass, String val, String con, boolean notNull, boolean notEmpty) {
        StringBuilder sql = new StringBuilder();
        sql.append("<set>");
        //获取全部列
        Set<EntityColumn> columnSet = EntityHelper.getColumns(entityClass);
        //对乐观锁的支持
        EntityColumn versionColumn = null;
        // 逻辑删除列
        EntityColumn logicDeleteColumn = null;
        //当某个列有主键策略时，不需要考虑他的属性是否为空，因为如果为空，一定会根据主键策略给他生成一个值
        for (EntityColumn column : columnSet) {
            if (column.getEntityField().isAnnotationPresent(Version.class)) {
                if (versionColumn != null) {
                    throw new VersionException(entityClass.getCanonicalName() + " 中包含多个带有 @Version 注解的字段，一个类中只能存在一个带有 @Version 注解的字段!");
                }
                versionColumn = column;
            }
            if (column.getEntityField().isAnnotationPresent(LogicDelete.class)) {
                if (logicDeleteColumn != null) {
                    throw new LogicDeleteException(entityClass.getCanonicalName() + " 中包含多个带有 @LogicDelete 注解的字段，一个类中只能存在一个带有 @LogicDelete 注解的字段!");
                }
                logicDeleteColumn = column;
            }
            if (!column.isId() && column.isUpdatable()) {
                if (column == versionColumn) {
                    Version version = versionColumn.getEntityField().getAnnotation(Version.class);
                    String versionClass = version.nextVersion().getCanonicalName();
                    sql.append("<bind name=\"").append(column.getProperty()).append("Version\" value=\"");
                    //version = ${@tk.mybatis.mapper.version@nextVersionClass("versionClass", version)}
                    sql.append("@tk.mybatis.mapper.version.VersionUtil@nextVersion(")
                        .append("@").append(versionClass).append("@class, ");
                    sql.append(condition(column, con)).append(")\"/>");
                    sql.append(column.getColumn()).append(" = #{").append(column.getProperty()).append("Version},");
                } else if (column == logicDeleteColumn) {
                    sql.append(SqlHelper.logicDeleteColumnEqualsValue(column, false)).append(",");
                } else if (notNull) {
                    sql.append(specialSetIfNotNull(column, val, con, notEmpty));
                } else {
                    sql.append(column.getColumnEqualsHolder(val) + ",");
                }
            }
        }
        sql.append("</set>");
        return sql.toString();
    }
    
    /**
     * 判断自动!=null的条件结构
     * @param column
     * @param val valueParamEntityName
     * @param con conditionParamEntityName
     * @param empty
     */
    public static String specialSetIfNotNull(EntityColumn column, String val, String con, boolean empty) {
        StringBuilder sql = new StringBuilder();
        sql.append("<if test=\"").append(condition(column, con)).append(" != null \">");
        sql.append(column.getColumnEqualsHolder(val));
        sql.append(",</if>");
        return sql.toString();
    }
//    public static String specialGetIfNotNull(EntityColumn column, String val, String con, boolean empty) {
//        StringBuilder sql = new StringBuilder();
//        sql.append("<choose><when test=\"");
//        sql.append(condition(column, con)).append(" == 'null' \">");;
//        
//        sql.append(column.getColumn() + " = null,"); // content
//        sql.append("</when>");
//        
//        sql.append("<when test=\"");
//        sql.append(condition(column, con)).append(" != null");
//        if (empty && column.getJavaType().equals(String.class)) {
//            sql.append(" and ");
//            sql.append(condition(column, con)).append(" != '' ");
//        }
//        sql.append("\">");
//        sql.append(column.getColumnEqualsHolder(val) + ","); // content
//        sql.append("</when></choose>");
//        return sql.toString();
//    }
    
    public static StringBuilder condition(EntityColumn column, String conditionParamEntityName) {
        StringBuilder sql = new StringBuilder();
        if (StringUtil.isNotEmpty(conditionParamEntityName)) {
            sql.append(conditionParamEntityName).append(".");
        }
        return sql.append(column.getProperty());
    }
    
}
